package com.devin.command;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.devin.ICommand;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 打印目录树
 */
@Parameters(commandDescription = "打印目录树")
public class DirTreeCommand implements ICommand {
    @Parameter(description = "指定的路径")
    private List<String> dirNames;

    @Parameter(names = "--exclude", description = "排除项（支持正则）")
    private List<String> excludes;

    private static final String BRANCH = "├─";
    private static final String LAST_BRANCH = "└─";
    private static final String TAB = "│  ";
    private static final String EMPTY_TAB = "   ";

    @Override
    public String getName() {
        return "tree";
    }

    @Override
    public boolean execute() {
        List<String> names = dirNames;
        if (names == null || names.isEmpty()) {
            names = new ArrayList<>();
            names.add(".");
        }
        for (String name : names) {
            StringBuilder sb = new StringBuilder();
            System.out.println(String.format("列出 %s 的目录树\n处理中...", name));
            parseTree(name, "", sb);
            System.out.println("处理完成，结果如下:");
            System.out.println(sb.toString());
        }
        return true;
    }

    /**
     * 遍历文件并拼接路径。
     *
     * @param path 路径
     * @param placeholder 格式化占位符
     * @param sb 缓存要打印的结果
     */
    private void parseTree(String path, String placeholder, StringBuilder sb) {
        if (exclude(path)) {
            return;
        }

        File file = new File(path);
        if (!file.exists()) {
            System.out.println(String.format("%s 不存在", path));
            return;
        }

        File[] files = file.listFiles();
        if (!file.isDirectory() || files == null || files.length == 0) {
            // 如果是根目录，则直接输出。防止空的子目录重复输出。
            if ("".equals(placeholder)) {
                sb.append(placeholder).append(LAST_BRANCH).append(file.getName()).append("\n");
            }
            return;
        }

        List<File> includeFiles = new ArrayList<>();
        for (int i = 0, length = files.length; i < length; i++) {
            if (!exclude(files[i].getName())) {
                includeFiles.add(files[i]);
            }
        }

        int index = 0, size = includeFiles.size();
        for (File include : includeFiles) {
            String branch = index == size - 1 ? LAST_BRANCH : BRANCH;
            sb.append(placeholder).append(branch).append(include.getName()).append("\n");
            if (include.isDirectory()) {
                parseTree(path + "/" + include.getName(),
                        ("".equals(placeholder) && !LAST_BRANCH.equals(branch))
                                ? TAB
                                : placeholder + (LAST_BRANCH.equals(branch) ? EMPTY_TAB : TAB), sb);
            }
            index++;
        }
    }

    /**
     * 按指定的排除规则进行排除。
     *
     * @param path 待排除的路径
     * @return true 需要排除，false 不需要排除。
     */
    private boolean exclude(String path) {
        if (excludes != null && !excludes.isEmpty()) {
            for (String exclude : excludes) {
                Pattern pattern = Pattern.compile(exclude);
                Matcher matcher = pattern.matcher(path);
                if (matcher.find()) {
                    return true;
                }
            }
        }
        return false;
    }
}
